use async_trait::async_trait;
use rustcloud_core::{
    ServiceRegistry, ServiceInstance, ServiceResult, ServiceError, RegistryType,
    ServiceWatcher, HealthCheck, ServiceFilter, HealthCheckType
};
use crate::RegistryConfig;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::{Duration, SystemTime};
use reqwest::Client;
use tracing::{error, warn, info, debug};

/// Consul服务实例注册数据结构
#[derive(Serialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct ConsulServiceRegistration {
    id: String,
    name: String,
    tags: Vec<String>,
    address: String,
    port: u16,
    meta: HashMap<String, String>,
    check: Option<ConsulHealthCheck>,
    weights: Option<ConsulWeights>,
}

/// Consul健康检查配置
#[derive(Serialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct ConsulHealthCheck {
    #[serde(skip_serializing_if = "Option::is_none")]
    http: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    tcp: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    script: Option<String>,
    interval: String,
    timeout: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    deregister_critical_service_after: Option<String>,
}

/// Consul权重配置
#[derive(Serialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct ConsulWeights {
    passing: u16,
    warning: u16,
}

/// Consul服务发现响应
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct ConsulServiceResponse {
    service: ConsulService,
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct ConsulService {
    id: String,
    service: String,
    tags: Vec<String>,
    address: String,
    port: u16,
    meta: HashMap<String, String>,
    weights: Option<ConsulServiceWeights>,
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct ConsulServiceWeights {
    passing: u16,
    warning: u16,
}

/// Consul健康状态响应
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct ConsulHealthResponse {
    node: ConsulNode,
    service: ConsulService,
    checks: Vec<ConsulCheck>,
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct ConsulNode {
    id: String,
    node: String,
    address: String,
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct ConsulCheck {
    node: String,
    #[serde(rename = "CheckID")]
    check_id: String,
    name: String,
    status: String,
    notes: String,
    output: String,
    #[serde(rename = "ServiceID")]
    service_id: String,
    service_name: String,
}

/// Consul服务注册中心实现
#[derive(Clone)]
pub struct ConsulRegistry {
    client: Client,
    config: RegistryConfig,
    base_url: String,
    service_cache: std::sync::Arc<tokio::sync::RwLock<HashMap<String, (Vec<ServiceInstance>, SystemTime)>>>,
    cache_ttl: Duration,
}

impl ConsulRegistry {
    pub fn new(config: RegistryConfig) -> ServiceResult<Self> {
        let client = Client::builder()
            .timeout(Duration::from_secs(30))
            .build()
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        if config.registry_type != RegistryType::Consul {
            return Err(ServiceError::ConfigurationError(
                format!("Expected Consul registry type, got: {}", config.registry_type)
            ));
        }

        let base_url = if config.server_addr.is_empty() {
            "http://127.0.0.1:8500".to_string()
        } else {
            config.server_addr.clone()
        };

        Ok(Self {
            client,
            config,
            base_url,
            service_cache: std::sync::Arc::new(tokio::sync::RwLock::new(HashMap::new())),
            cache_ttl: Duration::from_secs(30),
        })
    }

    /// 构建API URL
    fn build_url(&self, endpoint: &str) -> String {
        format!("{}/v1/{}", self.base_url, endpoint)
    }

    /// 生成服务实例ID
    fn generate_instance_id(&self, instance: &ServiceInstance) -> String {
        format!("{}:{}:{}", instance.service_id, instance.host, instance.port)
    }

    /// 将HealthCheck转换为Consul健康检查
    fn convert_health_check(&self, instance: &ServiceInstance, health_check: &HealthCheck) -> ConsulHealthCheck {
        let interval = format!("{}s", health_check.interval.as_secs());
        let timeout = format!("{}s", health_check.timeout.as_secs());

        match &health_check.check_type {
            HealthCheckType::Http { path, method: _ } => {
                let url = format!("{}://{}{}", instance.scheme, instance.address(), path);
                ConsulHealthCheck {
                    http: Some(url),
                    tcp: None,
                    script: None,
                    interval,
                    timeout,
                    deregister_critical_service_after: Some("90s".to_string()),
                }
            }
            HealthCheckType::Tcp => {
                let address = format!("{}:{}", instance.host, instance.port);
                ConsulHealthCheck {
                    http: None,
                    tcp: Some(address),
                    script: None,
                    interval,
                    timeout,
                    deregister_critical_service_after: Some("90s".to_string()),
                }
            }
            HealthCheckType::Script { command } => {
                ConsulHealthCheck {
                    http: None,
                    tcp: None,
                    script: Some(command.clone()),
                    interval,
                    timeout,
                    deregister_critical_service_after: Some("90s".to_string()),
                }
            }
        }
    }

    /// 检查服务缓存
    async fn get_cached_instances(&self, service_name: &str) -> Option<Vec<ServiceInstance>> {
        let cache = self.service_cache.read().await;
        if let Some((instances, cached_time)) = cache.get(service_name) {
            if cached_time.elapsed().unwrap_or(Duration::from_secs(u64::MAX)) < self.cache_ttl {
                return Some(instances.clone());
            }
        }
        None
    }

    /// 更新服务缓存
    async fn update_cache(&self, service_name: &str, instances: Vec<ServiceInstance>) {
        let mut cache = self.service_cache.write().await;
        cache.insert(service_name.to_string(), (instances, SystemTime::now()));
    }

    /// 获取所有服务列表
    async fn get_services(&self) -> ServiceResult<Vec<String>> {
        let url = self.build_url("catalog/services");
        
        let response = self.client.get(&url).send().await
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        if response.status().is_success() {
            let services: HashMap<String, Vec<String>> = response.json().await
                .map_err(|e| ServiceError::SerializationError(e.to_string()))?;
            
            Ok(services.keys().cloned().collect())
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(ServiceError::RegistryError(format!("Failed to get services: {}", error_text)))
        }
    }

    /// 检查Consul健康状态
    async fn check_consul_health(&self) -> ServiceResult<bool> {
        let url = self.build_url("status/leader");
        
        match self.client.get(&url).timeout(Duration::from_secs(5)).send().await {
            Ok(response) if response.status().is_success() => {
                // 如果能获取到leader信息，说明Consul集群是健康的
                Ok(true)
            }
            _ => Ok(false),
        }
    }
}

#[async_trait]
impl ServiceRegistry for ConsulRegistry {
    async fn register(&self, instance: ServiceInstance) -> ServiceResult<()> {
        let url = self.build_url("agent/service/register");
        let instance_id = self.generate_instance_id(&instance);
        
        // 准备标签，将元数据作为标签
        let mut tags = vec![];
        for (key, value) in &instance.metadata {
            tags.push(format!("{}:{}", key, value));
        }
        
        // 添加默认标签
        tags.push(format!("version:{}", instance.metadata.get("version").unwrap_or(&"1.0.0".to_string())));
        tags.push(format!("healthy:{}", instance.healthy));
        
        let registration = ConsulServiceRegistration {
            id: instance_id.clone(),
            name: instance.service_id.clone(),
            tags,
            address: instance.host.clone(),
            port: instance.port,
            meta: instance.metadata.clone(),
            check: None, // 基础注册不包含健康检查
            weights: Some(ConsulWeights {
                passing: (instance.weight * 100.0) as u16,
                warning: 1,
            }),
        };

        let response = self.client
            .put(&url)
            .json(&registration)
            .send()
            .await
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        if response.status().is_success() {
            info!("Successfully registered service instance: {} ({})", instance.service_id, instance_id);
            Ok(())
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(ServiceError::RegistryError(format!("Failed to register service: {}", error_text)))
        }
    }
    
    async fn register_with_metadata(&self, mut instance: ServiceInstance, metadata: HashMap<String, String>) -> ServiceResult<()> {
        instance.metadata.extend(metadata);
        self.register(instance).await
    }
    
    async fn register_with_health_check(&self, instance: ServiceInstance, health_check: HealthCheck) -> ServiceResult<()> {
        let url = self.build_url("agent/service/register");
        let instance_id = self.generate_instance_id(&instance);
        
        let mut tags = vec![];
        for (key, value) in &instance.metadata {
            tags.push(format!("{}:{}", key, value));
        }
        tags.push(format!("version:{}", instance.metadata.get("version").unwrap_or(&"1.0.0".to_string())));
        tags.push(format!("healthy:{}", instance.healthy));
        
        let consul_health_check = self.convert_health_check(&instance, &health_check);
        
        let registration = ConsulServiceRegistration {
            id: instance_id.clone(),
            name: instance.service_id.clone(),
            tags,
            address: instance.host.clone(),
            port: instance.port,
            meta: instance.metadata.clone(),
            check: Some(consul_health_check),
            weights: Some(ConsulWeights {
                passing: (instance.weight * 100.0) as u16,
                warning: 1,
            }),
        };

        let response = self.client
            .put(&url)
            .json(&registration)
            .send()
            .await
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        if response.status().is_success() {
            info!("Successfully registered service instance with health check: {} ({})", instance.service_id, instance_id);
            Ok(())
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(ServiceError::RegistryError(format!("Failed to register service with health check: {}", error_text)))
        }
    }

    async fn deregister(&self, instance: ServiceInstance) -> ServiceResult<()> {
        let instance_id = self.generate_instance_id(&instance);
        let url = self.build_url(&format!("agent/service/deregister/{}", instance_id));

        let response = self.client
            .put(&url)
            .send()
            .await
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        if response.status().is_success() {
            info!("Successfully deregistered service instance: {} ({})", instance.service_id, instance_id);
            Ok(())
        } else {
            let error_text = response.text().await.unwrap_or_default();
            Err(ServiceError::RegistryError(format!("Failed to deregister service: {}", error_text)))
        }
    }

    async fn discover(&self, service_name: &str) -> ServiceResult<Vec<ServiceInstance>> {
        // 检查缓存
        if let Some(cached_instances) = self.get_cached_instances(service_name).await {
            debug!("Returning cached instances for service: {}", service_name);
            return Ok(cached_instances);
        }
        
        let url = self.build_url(&format!("catalog/service/{}", service_name));

        let response = self.client
            .get(&url)
            .send()
            .await
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        let status = response.status();
        if status.is_success() {
            let services: Vec<ConsulServiceResponse> = response.json().await
                .map_err(|e| ServiceError::SerializationError(e.to_string()))?;

            let instances: Vec<ServiceInstance> = services
                .into_iter()
                .map(|resp| {
                    let mut instance = ServiceInstance::new(
                        resp.service.service,
                        resp.service.address,
                        resp.service.port,
                        "http"
                    );
                    
                    // 设置元数据
                    instance.metadata = resp.service.meta;
                    
                    // 从标签中提取信息
                    for tag in resp.service.tags {
                        if let Some((key, value)) = tag.split_once(':') {
                            match key {
                                "healthy" => {
                                    instance.healthy = value.parse().unwrap_or(true);
                                }
                                _ => {
                                    instance.metadata.insert(key.to_string(), value.to_string());
                                }
                            }
                        }
                    }
                    
                    // 设置权重
                    if let Some(weights) = resp.service.weights {
                        instance.weight = (weights.passing as f64) / 100.0;
                    }
                    
                    instance
                })
                .collect();

            // 更新缓存
            self.update_cache(service_name, instances.clone()).await;
            
            debug!("Discovered {} instances for service: {}", instances.len(), service_name);
            Ok(instances)
        } else {
            let error_text = response.text().await.unwrap_or_default();
            if status.as_u16() == 404 {
                // 服务不存在，返回空列表
                Ok(Vec::new())
            } else {
                Err(ServiceError::RegistryError(format!("Failed to discover service: {}", error_text)))
            }
        }
    }
    
    async fn discover_with_filter(&self, service_name: &str, filter: ServiceFilter) -> ServiceResult<Vec<ServiceInstance>> {
        let instances = self.discover(service_name).await?;
        let original_count = instances.len();
        let filtered_instances: Vec<ServiceInstance> = instances.into_iter().filter(|instance| {
            // 健康状态过滤
            if filter.healthy_only && !instance.healthy {
                return false;
            }
            
            // 元数据过滤
            for (key, value) in &filter.metadata_filters {
                if instance.metadata.get(key) != Some(value) {
                    return false;
                }
            }
            
            // 版本过滤
            if let Some(version) = &filter.version_filter {
                if instance.metadata.get("version") != Some(version) {
                    return false;
                }
            }
            
            true
        }).collect();
        
        debug!("Filtered {} instances for service: {} (original: {})", 
               filtered_instances.len(), service_name, original_count);
        Ok(filtered_instances)
    }

    async fn health_check(&self, service_name: &str) -> ServiceResult<Vec<ServiceInstance>> {
        let url = self.build_url(&format!("health/service/{}", service_name));
        let params = [("passing", "true")];

        let response = self.client
            .get(&url)
            .query(&params)
            .send()
            .await
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        let status = response.status();
        if status.is_success() {
            let health_responses: Vec<ConsulHealthResponse> = response.json().await
                .map_err(|e| ServiceError::SerializationError(e.to_string()))?;

            let instances: Vec<ServiceInstance> = health_responses
                .into_iter()
                .filter(|resp| {
                    // 只返回所有检查都通过的实例
                    resp.checks.iter().all(|check| check.status == "passing")
                })
                .map(|resp| {
                    let mut instance = ServiceInstance::new(
                        resp.service.service,
                        resp.service.address,
                        resp.service.port,
                        "http"
                    );
                    
                    instance.metadata = resp.service.meta;
                    instance.healthy = true; // 由于过滤了passing状态，所有返回的都是健康的
                    
                    if let Some(weights) = resp.service.weights {
                        instance.weight = (weights.passing as f64) / 100.0;
                    }
                    
                    instance
                })
                .collect();

            Ok(instances)
        } else {
            let error_text = response.text().await.unwrap_or_default();
            if status.as_u16() == 404 {
                Ok(Vec::new())
            } else {
                Err(ServiceError::RegistryError(format!("Failed to check service health: {}", error_text)))
            }
        }
    }
    
    async fn list_services(&self) -> ServiceResult<Vec<String>> {
        self.get_services().await
    }
    
    async fn registry_health(&self) -> ServiceResult<bool> {
        self.check_consul_health().await
    }

    async fn watch(&self, _service_name: &str) -> ServiceResult<Box<dyn ServiceWatcher + Send>> {
        // TODO: 实现Consul服务监听功能（使用Consul的blocking queries）
        Err(ServiceError::NotImplemented("Watch API not implemented for Consul yet".to_string()))
    }
}
